<!Doctype html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
	<title>Ruby 多线程 | 菜鸟教程</title>

  <meta name='robots' content='max-image-preview:large' />
<link rel='stylesheet' id='classic-theme-styles-css' href='../0/classic-themes.min.css?ver=6.2' type='text/css' media='all' />
<link rel="canonical" href="../ruby/ruby-multithreading.html" />
<meta name="keywords" content="Ruby 多线程">
<meta name="description" content="Ruby 多线程 每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。 线程是程序中一个单一的顺序控制流程，在单个程序中同时运行多个线程完成不同的工作,称为多线程。 Ruby 中我们可以通过 Thread 类来创建多线程，Ruby的线程是一个轻量级的，可以以高效的方式来实现并行的代码。  创建 Ruby 线程 要启动一个新的线程，只需要调用 Thread.new 即可:   [mycode3 type=&#039;ruby&..">
		
	<link rel="shortcut icon" href="https://static.runoob.com/images/favicon.ico">
	<link rel="stylesheet" href="../0/style.css?v=1.170" type="text/css" media="all" />	
	<link rel="stylesheet" href="../0/font-awesome.min.css" media="all" />	
  <!--[if gte IE 9]><!-->
  <script src=""></script>
  <!--<![endif]-->
  <!--[if lt IE 9]>
     <script src=""></script>
     <script src=""></script>
  <![endif]-->
  <link rel="apple-touch-icon" href="https://static.runoob.com/images/icon/mobile-icon.png"/>
  <meta name="apple-mobile-web-app-title" content="菜鸟教程">
</head>
<body>

<!--  头部 -->
<div class="container logo-search">

  <div class="col search row-search-mobile">
    <form action="index.php">
      <input class="placeholder" placeholder="搜索……" name="s" autocomplete="off">
      
    </form>
  </div>

  <div class="row">
    <div class="col logo">
      <h1><a href="../">菜鸟教程 -- 学的不仅是技术，更是梦想！</a></h1>
    </div>
        <div class="col right-list"> 
    <button class="btn btn-responsive-nav btn-inverse" data-toggle="collapse" data-target=".nav-main-collapse" id="pull" style=""> <i class="fa fa-navicon"></i> </button>
    </div>
        
    <div class="col search search-desktop last">
      <div class="search-input" >
      <form action="//www.runoob.com/" target="_blank">
        <input class="placeholder" id="s" name="s" placeholder="搜索……"  autocomplete="off" style="height: 44px;">
      </form>
      
      </div>
    </div>
  </div>
</div>



<!-- 导航栏 -->
<!-- 导航栏 -->
<div class="container navigation">
	<div class="row">
		<div class="col nav">
			<ul class="pc-nav" id="runoob-detail-nav">
				<li><a href="../">首页</a></li>
				<li><a href="../html/html-tutorial.html">HTML</a></li>
				<li><a href="../css/css-tutorial.html">CSS</a></li>
				<li><a href="../js/js-tutorial.html">JavaScript</a></li>
				<li><a href="javascript:void(0);" data-id="vue">Vue</a></li>
				<li><a href="javascript:void(0);" data-id="bootstrap">Bootstrap</a></li>
				<li><a href="../nodejs/nodejs-tutorial.html">NodeJS</a></li>
				<li><a href="../python3/python3-tutorial.html">Python3</a></li>
				<li><a href="../python/python-tutorial.html">Python2</a></li>
				<li><a href="../java/java-tutorial.html">Java</a></li>
				<li><a href="../cprogramming/c-tutorial.html">C</a></li>
				<li><a href="../cplusplus/cpp-tutorial.html">C++</a></li>
				<li><a href="../csharp/csharp-tutorial.html">C#</a></li>
				<li><a href="../go/go-tutorial.html">Go</a></li>
				<li><a href="../sql/sql-tutorial.html">SQL</a></li>
				<li><a href="../linux/linux-tutorial.html">Linux</a></li>
				<li><a href="../jquery/jquery-tutorial.html">jQuery</a></li>
				<li><a href="../browser-history">本地书签</a></li>
				<!--
			
				<li><a href="../w3cnote/knowledge-start.html" style="font-weight: bold;" onclick="_hmt.push(['_trackEvent', '星球', 'click', 'start'])" title="我的圈子">我的圈子</a></li>				
				<li><a href="javascript:;" class="runoob-pop">登录</a></li>
				-->
      		</ul>
			<ul class="mobile-nav">
				<li><a href="../">首页</a></li>
				<li><a href="../html/html-tutorial.html">HTML</a></li>
				<li><a href="../css/css-tutorial.html">CSS</a></li>
				<li><a href="../js/js-tutorial.html">JS</a></li>
				<li><a href="../browser-history">本地书签</a></li>
				<li><a href="javascript:void(0)" class="search-reveal">Search</a> </li>
			</ul>
			
		</div>
	</div>
</div>

<div class="container sub-navigation sub-navigation-articles" style="display:none">
	<div class="row">
		<div class="col nav-sub">
		<ul id="python">
			<li class="cat-item"><a href="../python3/python3-tutorial.html">Python3 教程 <i class="fa fa-external-link" aria-hidden="true"></i></a></li>
			<li class="cat-item"><a href="../python/python-tutorial.html">Python2 教程 <i class="fa fa-external-link" aria-hidden="true"></i></a></li>
		</ul>
		<ul id="vue">
			<li class="cat-item"><a href="../vue3/vue3-tutorial.html">Vue3 教程 <i class="fa fa-external-link" aria-hidden="true"></i></a></li>
			<li class="cat-item"><a href="../vue/vue-tutorial.html">vue2 教程 <i class="fa fa-external-link" aria-hidden="true"></i></a></li>
		</ul>

		<ul id="bootstrap">
			<li class="cat-item"><a href="../bootstrap/bootstrap-tutorial.html">Bootstrap3 教程 <i class="fa fa-external-link" aria-hidden="true"></i></a></li>
			<li class="cat-item"><a href="../bootstrap4/bootstrap4-tutorial.html">Bootstrap4 教程 <i class="fa fa-external-link" aria-hidden="true"></i></a></li>
			<li class="cat-item"><a href="../bootstrap5/bootstrap5-tutorial.html">Bootstrap5 教程 <i class="fa fa-external-link" aria-hidden="true"></i></a></li>
			<li class="cat-item"><a href="../bootstrap/bootstrap-v2-tutorial.html">Bootstrap2 教程 <i class="fa fa-external-link" aria-hidden="true"></i></a></li>
		</ul>
		</div>
	</div>
</div><!--  内容  -->
<div class="container main">
	<!-- 中间 -->
	<div class="row">
	
<div class="runoob-col-md2">
<div class="left-column">
	<div class="tab" style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">
	<i class="fa fa-list" aria-hidden="true"></i> 
	<span>Ruby 教程</span>
	<a data-cate="62" href="javascript:void(0);" title="夜间模式"  id="moon"><i class="fa fa-moon-o" aria-hidden="true" style="line-height: 28px;font-size: 1.2em;margin: 2px 4px 0;"></i></a>
	<a data-cate="62" style="display:none;" href="javascript:void(0);" title="日间模式"  id="sun" ><i class="fa fa-sun-o" aria-hidden="true" style="line-height: 28px;font-size: 1.2em;margin: 2px 4px 0;line-height: 28px;
}"></i></a>

	</div>
	<div class="sidebar-box gallery-list">
		<div class="design" id="leftcolumn">
						<a target="_top" title="Ruby 教程"  href="../ruby/ruby-tutorial.html" >
			Ruby 教程			</a>
						<a target="_top" title="Ruby 简介"  href="../ruby/ruby-intro.html" >
			Ruby 简介			</a>
						<a target="_top" title="Ruby 环境"  href="../ruby/ruby-environment.html" >
			Ruby 环境			</a>
						<a target="_top" title="Ruby 安装 &#8211; Linux"  href="../ruby/ruby-installation-unix.html" >
			Ruby 安装 - Linux			</a>
						<a target="_top" title="Ruby 安装 &#8211; Windows"  href="../ruby/ruby-installation-windows.html" >
			Ruby 安装 - Windows			</a>
			<a target="_top" title="Ruby 中文编码" href="ruby-encoding.html"> Ruby 中文编码 </a>			<a target="_top" title="Ruby 命令行选项"  href="../ruby/ruby-command-line-options.html" >
			Ruby 命令行选项			</a>
						<a target="_top" title="Ruby 环境变量"  href="../ruby/ruby-environment-variables.html" >
			Ruby 环境变量			</a>
						<a target="_top" title="Ruby 语法"  href="../ruby/ruby-syntax.html" >
			Ruby 语法			</a>
			<a target="_top" title="Ruby 数据类型" href="ruby-datatypes.html"> Ruby 数据类型 </a>			<a target="_top" title="Ruby 类和对象"  href="../ruby/ruby-class.html" >
			Ruby 类和对象			</a>
						<a target="_top" title="Ruby 类案例"  href="../ruby/ruby-class-case-study.html" >
			Ruby 类案例			</a>
						<a target="_top" title="Ruby 变量"  href="../ruby/ruby-variable.html" >
			Ruby 变量			</a>
						<a target="_top" title="Ruby 运算符"  href="../ruby/ruby-operator.html" >
			Ruby 运算符			</a>
						<a target="_top" title="Ruby 注释"  href="../ruby/ruby-comment.html" >
			Ruby 注释			</a>
						<a target="_top" title="Ruby 条件判断"  href="../ruby/ruby-decision.html" >
			Ruby 条件判断			</a>
						<a target="_top" title="Ruby 循环"  href="../ruby/ruby-loop.html" >
			Ruby 循环			</a>
						<a target="_top" title="Ruby 方法"  href="../ruby/ruby-method.html" >
			Ruby 方法			</a>
						<a target="_top" title="Ruby 块"  href="../ruby/ruby-block.html" >
			Ruby 块			</a>
						<a target="_top" title="Ruby 模块（Module）"  href="../ruby/ruby-module.html" >
			Ruby 模块（Module）			</a>
						<a target="_top" title="Ruby 字符串（String）"  href="../ruby/ruby-string.html" >
			Ruby 字符串（String）			</a>
						<a target="_top" title="Ruby 数组（Array）"  href="../ruby/ruby-array.html" >
			Ruby 数组（Array）			</a>
						<a target="_top" title="Ruby 哈希（Hash）"  href="../ruby/ruby-hash.html" >
			Ruby 哈希（Hash）			</a>
						<a target="_top" title="Ruby 日期 &#038; 时间（Date &#038; Time）"  href="../ruby/ruby-date-time.html" >
			Ruby 日期 & 时间			</a>
						<a target="_top" title="Ruby 范围（Range）"  href="../ruby/ruby-range.html" >
			Ruby 范围（Range）			</a>
						<a target="_top" title="Ruby 迭代器"  href="../ruby/ruby-iterators.html" >
			Ruby 迭代器			</a>
						<a target="_top" title="Ruby 文件的输入与输出"  href="../ruby/ruby-input-output.html" >
			Ruby 文件的输入与输出			</a>
						<a target="_top" title="Ruby File 类和方法"  href="../ruby/ruby-file-methods.html" >
			Ruby File 类和方法			</a>
						<a target="_top" title="Ruby Dir 类和方法"  href="../ruby/ruby-dir-methods.html" >
			Ruby Dir 类和方法			</a>
						<a target="_top" title="Ruby 异常"  href="../ruby/ruby-exceptions.html" >
			Ruby 异常			</a>
			<br><h2 class="left"><span class="left_h2">Ruby</span> 高级教程</h2>			<a target="_top" title="Ruby 面向对象"  href="../ruby/ruby-object-oriented.html" >
			Ruby 面向对象			</a>
						<a target="_top" title="Ruby 正则表达式"  href="../ruby/ruby-regular-expressions.html" >
			Ruby 正则表达式			</a>
						<a target="_top" title="Ruby 数据库访问 &#8211; DBI 教程"  href="../ruby/ruby-database-access.html" >
			Ruby 数据库访问 - DBI 教程			</a>
			<a target="_top" title="Ruby Mysql" href="ruby-mysql-mysql2.html"> Ruby Mysql </a>			<a target="_top" title="Ruby  CGI 编程"  href="../ruby/ruby-cgi.html" >
			Ruby  CGI 编程			</a>
						<a target="_top" title="Ruby CGI方法"  href="../ruby/ruby-cgi-methods.html" >
			Ruby CGI方法			</a>
						<a target="_top" title="Ruby CGI Cookie"  href="../ruby/ruby-cgi-cookies.html" >
			Ruby CGI Cookie			</a>
						<a target="_top" title="Ruby CGI Session"  href="../ruby/ruby-cgi-sessions.html" >
			Ruby CGI Session			</a>
						<a target="_top" title="Ruby 发送邮件 &#8211; SMTP"  href="../ruby/ruby-sending-email.html" >
			Ruby 发送邮件 - SMTP			</a>
						<a target="_top" title="Ruby Socket 编程"  href="../ruby/ruby-socket-programming.html" >
			Ruby Socket 编程			</a>
						<a target="_top" title="Ruby XML, XSLT 和 XPath 教程"  href="../ruby/ruby-xml-xslt-xpath.html" >
			Ruby XML, XSLT 和 XPath 教程			</a>
						<a target="_top" title="Ruby Web Service 应用 &#8211; SOAP4R"  href="../ruby/ruby-web-services.html" >
			Ruby Web Service			</a>
						<a target="_top" title="Ruby 多线程"  href="../ruby/ruby-multithreading.html" >
			Ruby 多线程			</a>
						<a target="_top" title="Ruby JSON"  href="../ruby/ruby-json.html" >
			Ruby JSON			</a>
						<a target="_top" title="Ruby RubyGems"  href="../ruby/ruby-rubygems.html" >
			Ruby RubyGems			</a>
				
		</div>
	</div>	
</div>
</div>	<div class="col middle-column">
		
	
	<div class="article">
		
		<div class="previous-next-links">
			<div class="previous-design-link"><i style="font-size:16px;" class="fa fa-arrow-left" aria-hidden="true"></i> <a href="../ruby/ruby-web-services.html" rel="prev"> Ruby Web Service 应用 &#8211; SOAP4R</a> </div>
			<div class="next-design-link"><a href="../ruby/ruby-datatypes.html" rel="next"> Ruby 数据类型</a> <i style="font-size:16px;" class="fa fa-arrow-right" aria-hidden="true"></i></div>
		</div>
<div class="article-heading-ad" style="display: block;">
<script async src=""
     crossorigin="anonymous"></script>
<!-- 728*90 固定 -->
<ins class="adsbygoogle"
     style="display:inline-block;width:728px;height:90px"
     data-ad-client="ca-pub-5751451760833794"
     data-ad-slot="2147566827"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>
		</div>
		<div class="article-body">
		
			<div class="article-intro" id="content">
			
			<h1>Ruby 多线程</h1>
<p>每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。</p>
<p>线程是程序中一个单一的顺序控制流程，在单个程序中同时运行多个线程完成不同的工作,称为多线程。</p>
<p>Ruby 中我们可以通过 Thread 类来创建多线程，Ruby的线程是一个轻量级的，可以以高效的方式来实现并行的代码。</p>
<hr>
<h2>创建 Ruby 线程</h2>
<p>要启动一个新的线程，只需要调用 Thread.new 即可:</p>
<div class="example">
<div class="example_code">
<div class="hl-main"><span class="hl-comment">#</span><span class="hl-comment"> 线程 #1 代码部分</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> {
  </span><span class="hl-comment">#</span><span class="hl-comment"> 线程 #2 执行代码</span><span class="hl-comment"></span><span class="hl-code">
}
</span><span class="hl-comment">#</span><span class="hl-comment"> 线程 #1 执行代码</span><span class="hl-comment"></span></div>
</div>
</div>
<h3>实例</h3>
<p>以下实例展示了如何在Ruby程序中使用多线程：</p>
<div class="example">
<h2 class="example">实例</h2>
<div class="example_code">
<div class="hl-main"><span class="hl-comment">#</span><span class="hl-comment">!/usr/bin/ruby</span><span class="hl-comment"></span><span class="hl-code">
 
</span><span class="hl-reserved">def</span><span class="hl-code"> </span><span class="hl-identifier">func1</span><span class="hl-code">
   </span><span class="hl-identifier">i</span><span class="hl-code">=</span><span class="hl-number">0</span><span class="hl-code">
   </span><span class="hl-reserved">while</span><span class="hl-code"> </span><span class="hl-identifier">i</span><span class="hl-code">&lt;=</span><span class="hl-number">2</span><span class="hl-code">
      </span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">func1 at: #{Time.now}</span><span class="hl-quotes">&quot;</span><span class="hl-code">
      </span><span class="hl-identifier">sleep</span><span class="hl-brackets">(</span><span class="hl-number">2</span><span class="hl-brackets">)</span><span class="hl-code">
      </span><span class="hl-identifier">i</span><span class="hl-code">=</span><span class="hl-identifier">i</span><span class="hl-code">+</span><span class="hl-number">1</span><span class="hl-code">
   </span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-reserved">end</span><span class="hl-code">
 
</span><span class="hl-reserved">def</span><span class="hl-code"> </span><span class="hl-identifier">func2</span><span class="hl-code">
   </span><span class="hl-identifier">j</span><span class="hl-code">=</span><span class="hl-number">0</span><span class="hl-code">
   </span><span class="hl-reserved">while</span><span class="hl-code"> </span><span class="hl-identifier">j</span><span class="hl-code">&lt;=</span><span class="hl-number">2</span><span class="hl-code">
      </span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">func2 at: #{Time.now}</span><span class="hl-quotes">&quot;</span><span class="hl-code">
      </span><span class="hl-identifier">sleep</span><span class="hl-brackets">(</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">
      </span><span class="hl-identifier">j</span><span class="hl-code">=</span><span class="hl-identifier">j</span><span class="hl-code">+</span><span class="hl-number">1</span><span class="hl-code">
   </span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-reserved">end</span><span class="hl-code">
 
</span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">Started At #{Time.now}</span><span class="hl-quotes">&quot;</span><span class="hl-code">
</span><span class="hl-identifier">t1</span><span class="hl-code">=</span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code">{</span><span class="hl-identifier">func1</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">}
</span><span class="hl-identifier">t2</span><span class="hl-code">=</span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code">{</span><span class="hl-identifier">func2</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">}
</span><span class="hl-identifier">t1</span><span class="hl-code">.</span><span class="hl-identifier">join</span><span class="hl-code">
</span><span class="hl-identifier">t2</span><span class="hl-code">.</span><span class="hl-identifier">join</span><span class="hl-code">
</span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">End at #{Time.now}</span><span class="hl-quotes">&quot;</span></div>
</div><br>
<a target="_blank" href="../try/runcode.php?filename=thread_demo&type=ruby" class="tryitbtn" rel="noopener noreferrer">尝试一下 »</a>
</div>
<p>以上代码执行结果为：</p>
<pre>
Started At Wed May 14 08:21:54 -0700 2014
func1 at: Wed May 14 08:21:54 -0700 2014
func2 at: Wed May 14 08:21:54 -0700 2014
func2 at: Wed May 14 08:21:55 -0700 2014
func1 at: Wed May 14 08:21:56 -0700 2014
func2 at: Wed May 14 08:21:56 -0700 2014
func1 at: Wed May 14 08:21:58 -0700 2014
End at Wed May 14 08:22:00 -0700 2014
</pre>
<h2>线程生命周期</h2>
<p>1、线程的创建可以使用Thread.new,同样可以以同样的语法使用Thread.start 或者Thread.fork这三个方法来创建线程。</p>
<p>2、创建线程后无需启动，线程会自动执行。</p>
<p>3、Thread 类定义了一些方法来操控线程。线程执行Thread.new中的代码块。</p>
<p>4、线程代码块中最后一个语句是线程的值，可以通过线程的方法来调用，如果线程执行完毕，则返回线程值，否则不返回值直到线程执行完毕。</p>
<p>5、Thread.current 方法返回表示当前线程的对象。  Thread.main 方法返回主线程。</p>
<p>6、通过 Thread.Join 方法来执行线程，这个方法会挂起主线程，直到当前线程执行完毕。</p>
<hr><h2>线程状态</h2>
<p>线程有5种状态：</p>
<table class="reference">
<tbody><tr><th style="width:50%">线程状态</th><th>返回值</th></tr>
<tr><td>可执行</td><td>run</td></tr>
<tr><td>睡眠</td><td>Sleeping</td></tr>
<tr><td>退出</td><td>aborting</td></tr>
<tr><td>正常终止</td><td>false </td></tr>
<tr><td>发生异常终止</td><td>nil </td></tr>
</tbody></table>
<hr>
<h2>线程和异常</h2>
<p>当某线程发生异常，且没有被rescue捕捉到时，该线程通常会被无警告地终止。但是，若有其它线程因为Thread#join的关系一直等待该线程的话，则等待的线程同样会被引发相同的异常。
</p>
<div class="example">
<div class="example_code">
<div class="hl-main"><span class="hl-reserved">begin</span><span class="hl-code">
  </span><span class="hl-identifier">t</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
    </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">pass</span><span class="hl-code">    </span><span class="hl-comment">#</span><span class="hl-comment"> 主线程确实在等join</span><span class="hl-comment"></span><span class="hl-code">
    </span><span class="hl-identifier">raise</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">unhandled exception</span><span class="hl-quotes">&quot;</span><span class="hl-code">
  </span><span class="hl-reserved">end</span><span class="hl-code">
  </span><span class="hl-identifier">t</span><span class="hl-code">.</span><span class="hl-identifier">join</span><span class="hl-code">
</span><span class="hl-reserved">rescue</span><span class="hl-code">
  </span><span class="hl-identifier">p</span><span class="hl-code"> </span><span class="hl-var">$!</span><span class="hl-code">  </span><span class="hl-comment">#</span><span class="hl-comment"> =&gt; &quot;unhandled exception&quot;</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-reserved">end</span></div>
</div>
</div>
<p>使用下列3个方法，就可以让解释器在某个线程因异常而终止时中断运行。</p>
<ul>
<li>启动脚本时指定<b>-d</b>选项，并以调试模时运行。</li>
<li>用<code>Thread.abort_on_exception</code>设置标志。</li>
<li>使用<code>Thread#abort_on_exception</code>对指定的线程设定标志。</li>
</ul>
<p>当使用上述3种方法之一后，整个解释器就会被中断。</p>
<div class="example">
<div class="example_code">
<div class="hl-main"><span class="hl-identifier">t</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> { ... }
</span><span class="hl-identifier">t</span><span class="hl-code">.</span><span class="hl-identifier">abort_on_exception</span><span class="hl-code"> = </span><span class="hl-reserved">true</span></div>
</div>
</div>
<hr>
<h2>线程同步控制</h2>
<p>在Ruby中，提供三种实现同步的方式，分别是：</p>
<p>1. 通过Mutex类实现线程同步</p>
<p>2. 监管数据交接的Queue类实现线程同步</p>
<p>3. 使用ConditionVariable实现同步控制</p>
<h3>通过Mutex类实现线程同步</h3>
<p>通过Mutex类实现线程同步控制，如果在多个线程钟同时需要一个程序变量，可以将这个变量部分使用lock锁定。
代码如下：</p>
<div class="example">
<h2 class="example">实例</h2>
<div class="example_code">
<div class="hl-main"><span class="hl-comment">#</span><span class="hl-comment">!/usr/bin/ruby</span><span class="hl-comment"></span><span class="hl-code">
 
</span><span class="hl-reserved">require</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">thread</span><span class="hl-quotes">&quot;</span><span class="hl-code">
</span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">Synchronize Thread</span><span class="hl-quotes">&quot;</span><span class="hl-code">
 
</span><span class="hl-var">@num</span><span class="hl-code">=</span><span class="hl-number">200</span><span class="hl-code">
</span><span class="hl-var">@mutex</span><span class="hl-code">=</span><span class="hl-identifier">Mutex</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code">
 
</span><span class="hl-reserved">def</span><span class="hl-code"> </span><span class="hl-identifier">buyTicket</span><span class="hl-brackets">(</span><span class="hl-identifier">num</span><span class="hl-brackets">)</span><span class="hl-code">
     </span><span class="hl-var">@mutex</span><span class="hl-code">.</span><span class="hl-identifier">lock</span><span class="hl-code">
          </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-var">@num</span><span class="hl-code">&gt;=</span><span class="hl-identifier">num</span><span class="hl-code">
               </span><span class="hl-var">@num</span><span class="hl-code">=</span><span class="hl-var">@num</span><span class="hl-code">-</span><span class="hl-identifier">num</span><span class="hl-code">
               </span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">you have successfully bought #{num} tickets</span><span class="hl-quotes">&quot;</span><span class="hl-code">
          </span><span class="hl-reserved">else</span><span class="hl-code">
               </span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">sorry,no enough tickets</span><span class="hl-quotes">&quot;</span><span class="hl-code">
          </span><span class="hl-reserved">end</span><span class="hl-code">
     </span><span class="hl-var">@mutex</span><span class="hl-code">.</span><span class="hl-identifier">unlock</span><span class="hl-code">
</span><span class="hl-reserved">end</span><span class="hl-code">
 
</span><span class="hl-identifier">ticket1</span><span class="hl-code">=</span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> </span><span class="hl-number">10</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
     </span><span class="hl-number">10.</span><span class="hl-identifier">times</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code"> |</span><span class="hl-identifier">value</span><span class="hl-code">|
     </span><span class="hl-identifier">ticketNum</span><span class="hl-code">=</span><span class="hl-number">15</span><span class="hl-code">
     </span><span class="hl-identifier">buyTicket</span><span class="hl-brackets">(</span><span class="hl-identifier">ticketNum</span><span class="hl-brackets">)</span><span class="hl-code">
     </span><span class="hl-identifier">sleep</span><span class="hl-code"> </span><span class="hl-number">0.01</span><span class="hl-code">
     </span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-reserved">end</span><span class="hl-code">
 
</span><span class="hl-identifier">ticket2</span><span class="hl-code">=</span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> </span><span class="hl-number">10</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
     </span><span class="hl-number">10.</span><span class="hl-identifier">times</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code"> |</span><span class="hl-identifier">value</span><span class="hl-code">|
     </span><span class="hl-identifier">ticketNum</span><span class="hl-code">=</span><span class="hl-number">20</span><span class="hl-code">
     </span><span class="hl-identifier">buyTicket</span><span class="hl-brackets">(</span><span class="hl-identifier">ticketNum</span><span class="hl-brackets">)</span><span class="hl-code">
     </span><span class="hl-identifier">sleep</span><span class="hl-code"> </span><span class="hl-number">0.01</span><span class="hl-code">
     </span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-reserved">end</span><span class="hl-code">
 
</span><span class="hl-identifier">sleep</span><span class="hl-code"> </span><span class="hl-number">1</span><span class="hl-code">
</span><span class="hl-identifier">ticket1</span><span class="hl-code">.</span><span class="hl-identifier">join</span><span class="hl-code">
</span><span class="hl-identifier">ticket2</span><span class="hl-code">.</span><span class="hl-identifier">join</span></div>
</div><br>
<a target="_blank" href="../try/runcode.php?filename=thread_demo2&type=ruby" class="tryitbtn" rel="noopener noreferrer">尝试一下 »</a>
</div>
<p>以上代码执行结果为：</p>

<pre>
Synchronize Thread
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
</pre>
<p>除了使用lock锁定变量，还可以使用try_lock锁定变量，还可以使用Mutex.synchronize同步对某一个变量的访问。</p>
<h3>监管数据交接的Queue类实现线程同步</h3>
<p>
Queue类就是表示一个支持线程的队列，能够同步对队列末尾进行访问。不同的线程可以使用统一个对类，但是不用担心这个队列中的数据是否能够同步，另外使用SizedQueue类能够限制队列的长度
</p><p>SizedQueue类能够非常便捷的帮助我们开发线程同步的应用程序，应为只要加入到这个队列中，就不用关心线程的同步问题。
</p>
<p>经典的生产者消费者问题：</p>
<div class="example">
<h2 class="example">实例</h2>
<div class="example_code">
<div class="hl-main"><span class="hl-comment">#</span><span class="hl-comment">!/usr/bin/ruby</span><span class="hl-comment"></span><span class="hl-code">
 
</span><span class="hl-reserved">require</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">thread</span><span class="hl-quotes">&quot;</span><span class="hl-code">
</span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">SizedQuee Test</span><span class="hl-quotes">&quot;</span><span class="hl-code">
 
</span><span class="hl-identifier">queue</span><span class="hl-code"> = </span><span class="hl-identifier">Queue</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code">
 
</span><span class="hl-identifier">producer</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
     </span><span class="hl-number">10.</span><span class="hl-identifier">times</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code"> |</span><span class="hl-identifier">i</span><span class="hl-code">|
          </span><span class="hl-identifier">sleep</span><span class="hl-code"> </span><span class="hl-identifier">rand</span><span class="hl-brackets">(</span><span class="hl-identifier">i</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-comment">#</span><span class="hl-comment"> 让线程睡眠一段时间</span><span class="hl-comment"></span><span class="hl-code">
          </span><span class="hl-identifier">queue</span><span class="hl-code"> &lt;&lt; </span><span class="hl-identifier">i</span><span class="hl-code">
          </span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">#{i} produced</span><span class="hl-quotes">&quot;</span><span class="hl-code">
     </span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-reserved">end</span><span class="hl-code">
 
</span><span class="hl-identifier">consumer</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
     </span><span class="hl-number">10.</span><span class="hl-identifier">times</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code"> |</span><span class="hl-identifier">i</span><span class="hl-code">|
          </span><span class="hl-identifier">value</span><span class="hl-code"> = </span><span class="hl-identifier">queue</span><span class="hl-code">.</span><span class="hl-identifier">pop</span><span class="hl-code">
          </span><span class="hl-identifier">sleep</span><span class="hl-code"> </span><span class="hl-identifier">rand</span><span class="hl-brackets">(</span><span class="hl-identifier">i</span><span class="hl-quotes">/</span><span class="hl-string">2)
          puts &quot;consumed #{value}&quot;
     end
end
 
consumer.join</span></div>
</div><br>
<a target="_blank" href="../try/runcode.php?filename=thread_demo3&type=ruby" class="tryitbtn" rel="noopener noreferrer">尝试一下 »</a>
</div>

<p>程序的输出：</p>
<pre>
SizedQuee Test
0 produced
1 produced
consumed 0
2 produced
consumed 1
consumed 2
3 produced
consumed 34 produced

consumed 4
5 produced
consumed 5
6 produced
consumed 6
7 produced
consumed 7
8 produced
9 produced
consumed 8
consumed 9
</pre>
<hr>
<h2>线程变量</h2>
<p>
线程可以有其私有变量，线程的私有变量在线程创建的时候写入线程。可以被线程范围内使用，但是不能被线程外部进行共享。
</p><p>但是有时候，线程的局部变量需要别别的线程或者主线程访问怎么办？ruby当中提供了允许通过名字来创建线程变量，类似的把线程看做hash式的散列表。通过[]=写入并通过[]读出数据。我们来看一下下面的代码：</p>
<div class="example">
<h2 class="example">实例</h2>
<div class="example_code">
<div class="hl-main"><span class="hl-comment">#</span><span class="hl-comment">!/usr/bin/ruby</span><span class="hl-comment"></span><span class="hl-code">
 
</span><span class="hl-identifier">count</span><span class="hl-code"> = </span><span class="hl-number">0</span><span class="hl-code">
</span><span class="hl-identifier">arr</span><span class="hl-code"> = </span><span class="hl-brackets">[</span><span class="hl-brackets">]</span><span class="hl-code">
 
</span><span class="hl-number">10.</span><span class="hl-identifier">times</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code"> |</span><span class="hl-identifier">i</span><span class="hl-code">|
   </span><span class="hl-identifier">arr</span><span class="hl-brackets">[</span><span class="hl-identifier">i</span><span class="hl-brackets">]</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> {
      </span><span class="hl-identifier">sleep</span><span class="hl-brackets">(</span><span class="hl-identifier">rand</span><span class="hl-brackets">(</span><span class="hl-number">0</span><span class="hl-brackets">)</span><span class="hl-quotes">/</span><span class="hl-string">10.0)
      Thread.current[&quot;mycount&quot;] = count
      count += 1
   }
end
 
arr.each {|t| t.join; print t[&quot;mycount&quot;], &quot;, &quot; }
puts &quot;count = #{count}&quot;</span></div>
</div>
</div>
<p>以上代码运行输出结果为：</p>
<pre>
8, 0, 3, 7, 2, 1, 6, 5, 4, 9, count = 10
</pre>
<p>
主线程等待子线程执行完成，然后分别输出每个值。
。</p>
<hr>
<h2>线程优先级</h2>
<p>线程的优先级是影响线程的调度的主要因素。其他因素包括占用CPU的执行时间长短，线程分组调度等等。</p>

<p>可以使用 Thread.priority 方法得到线程的优先级和使用 Thread.priority= 方法来调整线程的优先级。</p>
<p>线程的优先级默认为 0 。 优先级较高的执行的要快。</p>
<p>一个 Thread 可以访问自己作用域内的所有数据，但如果有需要在某个线程内访问其他线程的数据应该怎么做呢？ Thread 类提供了线程数据互相访问的方法，你可以简单的把一个线程作为一个 Hash 表，可以在任何线程内使用 []= 写入数据，使用 [] 读出数据。
 </p>
<div class="example">
<div class="example_code">
<div class="hl-main"><span class="hl-identifier">athr</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> { </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">current</span><span class="hl-brackets">[</span><span class="hl-quotes">&quot;</span><span class="hl-string">name</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">]</span><span class="hl-code"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">Thread A</span><span class="hl-quotes">&quot;</span><span class="hl-code">; </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">stop</span><span class="hl-code"> }
</span><span class="hl-identifier">bthr</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> { </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">current</span><span class="hl-brackets">[</span><span class="hl-quotes">&quot;</span><span class="hl-string">name</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">]</span><span class="hl-code"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">Thread B</span><span class="hl-quotes">&quot;</span><span class="hl-code">; </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">stop</span><span class="hl-code"> }
</span><span class="hl-identifier">cthr</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> { </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">current</span><span class="hl-brackets">[</span><span class="hl-quotes">&quot;</span><span class="hl-string">name</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">]</span><span class="hl-code"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">Thread C</span><span class="hl-quotes">&quot;</span><span class="hl-code">; </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">stop</span><span class="hl-code"> }
</span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">list</span><span class="hl-code">.</span><span class="hl-identifier">each</span><span class="hl-code"> {|</span><span class="hl-identifier">x</span><span class="hl-code">| </span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">#{x.inspect}: #{x[</span><span class="hl-quotes">&quot;</span><span class="hl-identifier">name</span><span class="hl-quotes">&quot;</span><span class="hl-string">]}</span><span class="hl-quotes">&quot;</span><span class="hl-code"> }</span></div>
</div>
</div><p>
可以看到，把线程作为一个 Hash 表，使用 [] 和 []= 方法，我们实现了线程之间的数据共享。</p>
<hr>
<h2>线程互斥</h2>
<p>Mutex(Mutal Exclusion = 互斥锁)是一种用于多线程编程中，防止两条线程同时对同一公共资源（比如全局变量）进行读写的机制。</p>
<h3>不使用Mutax的实例</h3>
<div class="example">
<h2 class="example">实例</h2>
<div class="example_code">
<div class="hl-main"><span class="hl-comment">#</span><span class="hl-comment">!/usr/bin/ruby</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-reserved">require</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">thread</span><span class="hl-quotes">'</span><span class="hl-code">
 
</span><span class="hl-identifier">count1</span><span class="hl-code"> = </span><span class="hl-identifier">count2</span><span class="hl-code"> = </span><span class="hl-number">0</span><span class="hl-code">
</span><span class="hl-identifier">difference</span><span class="hl-code"> = </span><span class="hl-number">0</span><span class="hl-code">
</span><span class="hl-identifier">counter</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
   </span><span class="hl-identifier">loop</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
      </span><span class="hl-identifier">count1</span><span class="hl-code"> += </span><span class="hl-number">1</span><span class="hl-code">
      </span><span class="hl-identifier">count2</span><span class="hl-code"> += </span><span class="hl-number">1</span><span class="hl-code">
   </span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-identifier">spy</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
   </span><span class="hl-identifier">loop</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
      </span><span class="hl-identifier">difference</span><span class="hl-code"> += </span><span class="hl-brackets">(</span><span class="hl-identifier">count1</span><span class="hl-code"> - </span><span class="hl-identifier">count2</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">abs</span><span class="hl-code">
   </span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-identifier">sleep</span><span class="hl-code"> </span><span class="hl-number">1</span><span class="hl-code">
</span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">count1 :  #{count1}</span><span class="hl-quotes">&quot;</span><span class="hl-code">
</span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">count2 :  #{count2}</span><span class="hl-quotes">&quot;</span><span class="hl-code">
</span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">difference : #{difference}</span><span class="hl-quotes">&quot;</span></div>
</div>
</div>
<p>以上实例运行输出结果为：</p>
<pre>
count1 :  9712487
count2 :  12501239
difference : 0
</pre><h3>使用 mutex 的实例</h3>
<div class="example">
<h2 class="example">实例</h2>
<div class="example_code">
<div class="hl-main"><span class="hl-comment">#</span><span class="hl-comment">!/usr/bin/ruby</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-reserved">require</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">thread</span><span class="hl-quotes">'</span><span class="hl-code">
</span><span class="hl-identifier">mutex</span><span class="hl-code"> = </span><span class="hl-identifier">Mutex</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code">
 
</span><span class="hl-identifier">count1</span><span class="hl-code"> = </span><span class="hl-identifier">count2</span><span class="hl-code"> = </span><span class="hl-number">0</span><span class="hl-code">
</span><span class="hl-identifier">difference</span><span class="hl-code"> = </span><span class="hl-number">0</span><span class="hl-code">
</span><span class="hl-identifier">counter</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
   </span><span class="hl-identifier">loop</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
      </span><span class="hl-identifier">mutex</span><span class="hl-code">.</span><span class="hl-identifier">synchronize</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
         </span><span class="hl-identifier">count1</span><span class="hl-code"> += </span><span class="hl-number">1</span><span class="hl-code">
         </span><span class="hl-identifier">count2</span><span class="hl-code"> += </span><span class="hl-number">1</span><span class="hl-code">
      </span><span class="hl-reserved">end</span><span class="hl-code">
    </span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-identifier">spy</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
   </span><span class="hl-identifier">loop</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
       </span><span class="hl-identifier">mutex</span><span class="hl-code">.</span><span class="hl-identifier">synchronize</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">
          </span><span class="hl-identifier">difference</span><span class="hl-code"> += </span><span class="hl-brackets">(</span><span class="hl-identifier">count1</span><span class="hl-code"> - </span><span class="hl-identifier">count2</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">abs</span><span class="hl-code">
       </span><span class="hl-reserved">end</span><span class="hl-code">
   </span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-identifier">sleep</span><span class="hl-code"> </span><span class="hl-number">1</span><span class="hl-code">
</span><span class="hl-identifier">mutex</span><span class="hl-code">.</span><span class="hl-identifier">lock</span><span class="hl-code">
</span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">count1 :  #{count1}</span><span class="hl-quotes">&quot;</span><span class="hl-code">
</span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">count2 :  #{count2}</span><span class="hl-quotes">&quot;</span><span class="hl-code">
</span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">difference : #{difference}</span><span class="hl-quotes">&quot;</span></div>
</div>
</div>
<p>以上实例运行输出结果为：</p>
<pre>
count1 :  1336406
count2 :  1336406
difference : 0
</pre>
<hr>
<h2>死锁</h2>
<p>两个以上的运算单元，双方都在等待对方停止运行，以获取系统资源，但是没有一方提前退出时，这种状况，就称为死锁。</p>
<p>例如，一个进程 p1占用了显示器，同时又必须使用打印机，而打印机被进程p2占用，p2又必须使用显示器，这样就形成了死锁。</p>
<p>
当我们在使用 Mutex 对象时需要注意线程死锁。</p>
<div class="example">
<h2 class="example">实例</h2>
<div class="example_code">
<div class="hl-main"><span class="hl-comment">#</span><span class="hl-comment">!/usr/bin/ruby</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-reserved">require</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">thread</span><span class="hl-quotes">'</span><span class="hl-code">
</span><span class="hl-identifier">mutex</span><span class="hl-code"> = </span><span class="hl-identifier">Mutex</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code">
 
</span><span class="hl-identifier">cv</span><span class="hl-code"> = </span><span class="hl-identifier">ConditionVariable</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code">
</span><span class="hl-identifier">a</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> {
   </span><span class="hl-identifier">mutex</span><span class="hl-code">.</span><span class="hl-identifier">synchronize</span><span class="hl-code"> {
      </span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">A: I have critical section, but will wait for cv</span><span class="hl-quotes">&quot;</span><span class="hl-code">
      </span><span class="hl-identifier">cv</span><span class="hl-code">.</span><span class="hl-identifier">wait</span><span class="hl-brackets">(</span><span class="hl-identifier">mutex</span><span class="hl-brackets">)</span><span class="hl-code">
      </span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">A: I have critical section again! I rule!</span><span class="hl-quotes">&quot;</span><span class="hl-code">
   }
}
 
</span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">(Later, back at the ranch...)</span><span class="hl-quotes">&quot;</span><span class="hl-code">
 
</span><span class="hl-identifier">b</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> {
   </span><span class="hl-identifier">mutex</span><span class="hl-code">.</span><span class="hl-identifier">synchronize</span><span class="hl-code"> {
      </span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">B: Now I am critical, but am done with cv</span><span class="hl-quotes">&quot;</span><span class="hl-code">
      </span><span class="hl-identifier">cv</span><span class="hl-code">.</span><span class="hl-identifier">signal</span><span class="hl-code">
      </span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">B: I am still critical, finishing up</span><span class="hl-quotes">&quot;</span><span class="hl-code">
   }
}
</span><span class="hl-identifier">a</span><span class="hl-code">.</span><span class="hl-identifier">join</span><span class="hl-code">
</span><span class="hl-identifier">b</span><span class="hl-code">.</span><span class="hl-identifier">join</span></div>
</div>
</div>
<p>以上实例输出结果为：</p>
<pre>
A: I have critical section, but will wait for cv
(Later, back at the ranch...)
B: Now I am critical, but am done with cv
B: I am still critical, finishing up
A: I have critical section again! I rule!
</pre>
<h2>线程类方法</h2>
<p>完整的 Thread（线程） 类方法如下：</p>
<table class="reference">
<tbody><tr><th style="width:5%">序号</th><th>方法描述</th></tr>
<tr><td>1</td><td><b>Thread.abort_on_exception</b><br>若其值为真的话，一旦某线程因异常而终止时，整个解释器就会被中断。它的默认值是假，也就是说，在通常情况下，若某线程发生异常且该异常未被Thread#join等检测到时，该线程会被无警告地终止。</td></tr>
<tr><td>2</td><td><b>Thread.abort_on_exception=</b><br>如果设置为 <i>true</i>, 一旦某线程因异常而终止时，整个解释器就会被中断。返回新的状态</td></tr>
<tr><td>3</td><td><b>Thread.critical</b><br>返回布尔值。</td></tr>
<tr><td>4</td><td><b>Thread.critical=</b><br>当其值为true时，将不会进行线程切换。若当前线程挂起(stop)或有信号(signal)干预时，其值将自动变为false。</td></tr>
<tr><td>5</td><td><b>Thread.current</b><br>返回当前运行中的线程(当前线程)。</td></tr>
<tr><td>6</td><td><b>Thread.exit</b><br>终止当前线程的运行。返回当前线程。若当前线程是唯一的一个线程时，将使用exit(0)来终止它的运行。</td></tr>
<tr><td>7</td><td><b>Thread.fork { block }</b><br>与 Thread.new 一样生成线程。</td></tr>
<tr><td>8</td><td><b>Thread.kill( aThread )</b><br>终止线程的运行.</td></tr>
<tr><td>9</td><td><b>Thread.list</b><br>返回处于运行状态或挂起状态的活线程的数组。</td></tr>
<tr><td>10</td><td><b>Thread.main</b><br>返回主线程。</td></tr>
<tr><td>11</td><td><b>Thread.new( [ arg ]* ) {| args | block }</b><br>生成线程,并开始执行。数会被原封不动地传递给块. 这就可以在启动线程的同时,将值传递给该线程所固有的局部变量。</td></tr>
<tr><td>12</td><td><b>Thread.pass</b><br>将运行权交给其他线程. 它不会改变运行中的线程的状态,而是将控制权交给其他可运行的线程(显式的线程调度)。</td></tr>
<tr><td>13</td><td><b>Thread.start( [ args ]* ) {| args | block }</b><br>生成线程,并开始执行。数会被原封不动地传递给块. 这就可以在启动线程的同时,将值传递给该线程所固有的局部变量。</td></tr>
<tr><td>14</td><td><b>Thread.stop</b><br>将当前线程挂起,直到其他线程使用run方法再次唤醒该线程。</td></tr>
</tbody></table>
<hr>
<h2>线程实例化方法</h2>
<p>以下实例调用了线程实例化方法 join：</p>
<div class="example">
<h2 class="example">实例</h2>
<div class="example_code">
<div class="hl-main"><span class="hl-comment">#</span><span class="hl-comment">!/usr/bin/ruby</span><span class="hl-comment"></span><span class="hl-code">
 
</span><span class="hl-identifier">thr</span><span class="hl-code"> = </span><span class="hl-identifier">Thread</span><span class="hl-code">.</span><span class="hl-identifier">new</span><span class="hl-code"> </span><span class="hl-reserved">do</span><span class="hl-code">   </span><span class="hl-comment">#</span><span class="hl-comment"> 实例化</span><span class="hl-comment"></span><span class="hl-code">
   </span><span class="hl-identifier">puts</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">In second thread</span><span class="hl-quotes">&quot;</span><span class="hl-code">
   </span><span class="hl-identifier">raise</span><span class="hl-code"> </span><span class="hl-quotes">&quot;</span><span class="hl-string">Raise exception</span><span class="hl-quotes">&quot;</span><span class="hl-code">
</span><span class="hl-reserved">end</span><span class="hl-code">
</span><span class="hl-identifier">thr</span><span class="hl-code">.</span><span class="hl-identifier">join</span><span class="hl-code">   </span><span class="hl-comment">#</span><span class="hl-comment"> 调用实例化方法 join</span><span class="hl-comment"></span></div>
</div>
</div>

<p>以下是完整实例化方法列表：</p>
<table class="reference">
<tbody><tr><th style="width:5%">序号</th><th>方法描述</th></tr>
<tr><td>1</td><td><b>thr[ name ]</b><br>取出线程内与name相对应的固有数据。 name可以是字符串或符号。

若没有与name相对应的数据时, 返回nil。</td></tr>
<tr><td>2</td><td><b>thr[ name ] =</b><br>设置线程内name相对应的固有数据的值， name可以是字符串或符号。 若设为nil时, 将删除该线程内对应数据。</td></tr>
<tr><td>3</td><td><b>thr.abort_on_exception</b><br>返回布尔值。</td></tr>
<tr><td>4</td><td><b>thr.abort_on_exception=</b><br>若其值为true的话，一旦某线程因异常而终止时，整个解释器就会被中断。</td></tr>
<tr><td>5</td><td><b>thr.alive?</b><br>若线程是"活"的,就返回true。</td></tr>
<tr><td>6</td><td><b>thr.exit</b><br>终止线程的运行。返回self。</td></tr>
<tr><td>7</td><td><b>thr.join</b><br>挂起当前线程,直到self线程终止运行为止. 若self因异常而终止时, 将会当前线程引发同样的异常。</td></tr>
<tr><td>8</td><td><b>thr.key?</b><br>若与name相对应的线程固有数据已经被定义的话,就返回true</td></tr>
<tr><td>9</td><td><b>thr.kill</b><br>类似于 <i>Thread.exit</i> 。</td></tr>
<tr><td>10</td><td><b>thr.priority</b><br>返回线程的优先度. 优先度的默认值为0. 该值越大则优先度越高.</td></tr>
<tr><td>11</td><td><b>thr.priority=</b><br>设定线程的优先度. 也可以将其设定为负数.</td></tr>
<tr><td>12</td><td><b>thr.raise( anException )</b><br>在该线程内强行引发异常.</td></tr>
<tr><td>13</td><td><b>thr.run</b><br>重新启动被挂起(stop)的线程. 与wakeup不同的是,它将立即进行线程的切换. 若对死进程使用该方法时, 将引发ThreadError异常.</td></tr>
<tr><td>14</td><td><b>thr.safe_level</b><br>返回self 的安全等级. 当前线程的safe_level与$SAFE相同.</td></tr>
<tr><td>15</td><td><b>thr.status</b><br>使用字符串"run"、"sleep"或"aborting" 来表示活线程的状态. 若某线程是正常终止的话,就返回false. 若因异常而终止的话,就返回nil。</td></tr>
<tr><td>16</td><td><b>thr.stop?</b><br>若线程处于终止状态(dead)或被挂起(stop)时,返回true.</td></tr>
<tr><td>17</td><td><b>thr.value</b><br>一直等到self线程终止运行(等同于join)后,返回该线程的块的返回值. 若在线程的运行过程中发生了异常, 就会再次引发该异常.</td></tr>
<tr><td>18</td><td><b>thr.wakeup</b><br>把被挂起(stop)的线程的状态改为可执行状态(run), 若对死线程执行该方法时,将会引发ThreadError异常。</td></tr>
</tbody></table>			<!-- 其他扩展 -->
						
			</div>
			
		</div>
		
		<div class="previous-next-links">
			<div class="previous-design-link"><i style="font-size:16px;" class="fa fa-arrow-left" aria-hidden="true"></i> <a href="../ruby/ruby-web-services.html" rel="prev"> Ruby Web Service 应用 &#8211; SOAP4R</a> </div>
			<div class="next-design-link"><a href="../ruby/ruby-datatypes.html" rel="next"> Ruby 数据类型</a> <i style="font-size:16px;" class="fa fa-arrow-right" aria-hidden="true"></i></div>
		</div>
		<!-- 笔记列表 -->
		<style>
.wrapper {
  /*text-transform: uppercase; */
  background: #ececec;
  color: #555;
  cursor: help;
  font-family: "Gill Sans", Impact, sans-serif;
  font-size: 20px;
  position: relative;
  text-align: center;
  width: 200px;
  -webkit-transform: translateZ(0); /* webkit flicker fix */
  -webkit-font-smoothing: antialiased; /* webkit text rendering fix */
}

.wrapper .tooltip {
  white-space: nowrap;
  font-size: 14px;
  text-align: left;
  background: #96b97d;
  bottom: 100%;
  color: #fff;
  display: block;
  left: -25px;
  margin-bottom: 15px;
  opacity: 0;
  padding: 14px;
  pointer-events: none;
  position: absolute;
  
  -webkit-transform: translateY(10px);
     -moz-transform: translateY(10px);
      -ms-transform: translateY(10px);
       -o-transform: translateY(10px);
          transform: translateY(10px);
  -webkit-transition: all .25s ease-out;
     -moz-transition: all .25s ease-out;
      -ms-transition: all .25s ease-out;
       -o-transition: all .25s ease-out;
          transition: all .25s ease-out;
  -webkit-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
     -moz-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
      -ms-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
       -o-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
          box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
}
.tooltip a {
	color:#fff;
}
/* This bridges the gap so you can mouse into the tooltip without it disappearing */
.wrapper .tooltip:before {
  bottom: -20px;
  content: " ";
  display: block;
  height: 20px;
  left: 0;
  position: absolute;
  width: 100%;
}  

/* CSS Triangles - see Trevor's post */
.wrapper .tooltip:after {
  border-left: solid transparent 10px;
  border-right: solid transparent 10px;
  border-top: solid #96b97d 10px;
  bottom: -10px;
  content: " ";
  height: 0;
  left: 20%;
  margin-left: -13px;
  position: absolute;
  width: 0;
}
.wrapper .tooltip1 {
	margin-left: 50px;
	padding-top: 0px;
}
/*
.wrapper:hover .tooltip {
  opacity: 1;
  pointer-events: auto;
  -webkit-transform: translateY(0px);
     -moz-transform: translateY(0px);
      -ms-transform: translateY(0px);
       -o-transform: translateY(0px);
          transform: translateY(0px);
}
*/
/* IE can just show/hide with no transition */
.lte8 .wrapper .tooltip {
  display: none;
}

.lte8 .wrapper:hover .tooltip {
  display: block;
}

</style>

<link rel="stylesheet" href="../0/upvotejs.css">
<script src=""></script>
<script src=""></script>
<div id="respond" class="no_webshot"> 
		<div class="comment-signarea" style=" padding: 20px 20px;"> 
	<h3 class="text-muted" id="share_code" style="color: #799961;"><i class="fa fa-pencil-square-o" aria-hidden="true"></i> 点我分享笔记</h3>
	<!--
	<p style="font-size:14px;">笔记需要是本篇文章的内容扩展！</p><br>
	<p style="font-size:12px;"><a href="../tougao" target="_blank">文章投稿，可点击这里</a></p>
	<p style="font-size:14px;"><a href="../w3cnote/runoob-user-test-intro.html#invite" target="_blank">注册邀请码获取方式</a></p>
		<h3 class="text-muted"><i class="fa fa-info-circle" aria-hidden="true"></i> 分享笔记前必须<a href="javascript:;" class="runoob-pop">登录</a>！</h3>
		<p><a href="../w3cnote/runoob-user-test-intro.html#invite" target="_blank">注册邀请码获取方式</a></p>-->
	</div>
		
	<form action="/wp-content/themes/runoob/option/addnote.php" method="post" id="commentform" style="display:none;">
		<div class="comt">
			<div class="comt-title">
				<i style="font-size:36px;" class="fa fa-user-circle" aria-hidden="true"></i>				<p><a id="cancel-comment-reply-link" href="javascript:;">取消</a></p>
			</div>
			<div class="comt-box">
			<div id="mded"></div>
			
				<div class="comt-ctrl">
					<div class="comt-tips"><input type='hidden' name='comment_post_ID' value='7658' id='comment_post_ID' />
<input type='hidden' name='comment_parent' id='comment_parent' value='0' />
</div>
					<button type="submit" name="submit" id="submit" tabindex="5"><i class="fa fa-pencil" aria-hidden="true"></i> 分享笔记</button>
				</div>
			</div>
		
				
					<div class="comt-comterinfo"> 
						<ul id="comment-author-info">
							<li class="form-inline"><label class="hide" for="author">昵称</label><input class="ipt" type="text" name="author" id="author" value="" tabindex="2" placeholder="昵称"><span class="text-muted">昵称 (必填)</span></li>
							<li class="form-inline"><label class="hide" for="email">邮箱</label><input class="ipt" type="text" name="email" id="email" value="" tabindex="3" placeholder="邮箱"><span class="text-muted">邮箱 (必填)</span></li>
							<li class="form-inline"><label class="hide" for="url">引用地址</label><input class="ipt" type="text" name="url" id="url" value="" tabindex="4" placeholder="引用地址"><span class="text-muted">引用地址</span></li>
						</ul>
					</div>
				
			
		</div>

	</form>
	</div>
<script type="text/javascript">
$(function() {
	//初始化编辑器
	
	var editor = new Simditor({
	  textarea: $('#mded'),
	  placeholder: '写笔记...',
	  upload:false,
	 // upload: {url:'/api/comment_upload_file.php',params: null,fileKey: 'upload_file',connectionCount: 1,leaveConfirm: '文件正在上传，您确定离开?'},
	  defaultImage: 'https://www.runoob.com/images/logo.png',
	  codeLanguages: '',
	  autosave: 'editor-content',
	  toolbar: [  'bold','code','ul','ol','image' ]
	});
	editor.on('selectionchanged', function() {
		$(".code-popover").hide();
	});

	// 提交数据
	$("#share_code").click(function() {
		$(".comment-signarea").hide();
		$("#commentform").show();
		
	});
	$("#user_add_note").click(function() {
		$(".comment-signarea").hide();
		$("#commentform").show();
		$('html, body').animate({
       	    scrollTop: $("#respond").offset().top
    	}, 200);
	});

	// 提交笔记
	var commentform=$('#commentform');
	commentform.prepend('<div id="comment-status" style="display:none;" ></div>');
	var statusdiv=$('#comment-status');
	
	commentform.submit(function(e){
		e.preventDefault();
		var noteContent = editor.getValue();
		// console.log(noteContent);
		noteContent = noteContent.replace(/<pre><code>/g,"<pre>");
		noteContent = noteContent.replace(/<\/code><\/pre>/g,"</pre>");
		
		// 系列化表单数据
		var comment_parent = 0;
		var is_user_logged_in = $("#is_user_logged_in").val();
		var comment_post_ID =  7658;
		var _wp_unfiltered_html_comment = $("#_wp_unfiltered_html_comment").val();
		var comment = noteContent;
		var author = $("#author").val();
		var url = $("#url").val();
		var email = $("#email").val();
		if(isBlank(author) && is_user_logged_in==0) {
			statusdiv.html('<p  class="ajax-error">请输入昵称！</p>').show();
		} else if(isBlank(email)  && is_user_logged_in==0) {
			statusdiv.html('<p  class="ajax-error">请输入邮箱！</p>').show();
		} else {
			// var formdata=commentform.serialize() + "&comment=" + noteContent ;
			// 添加状态信息
			statusdiv.html('<p>Processing...</p>').show();
			// 获取表单提交地址
			var formurl=commentform.attr('action');
			
			// 异步提交
			$.ajax({
					type: 'post',
					url: formurl,
					dataType:'json',
					data: {"comment_parent":comment_parent,"comment_post_ID":comment_post_ID, "_wp_unfiltered_html_comment":_wp_unfiltered_html_comment,"comment":comment,"url":url, "email":email,"author":author},
					error: function(XMLHttpRequest, textStatus, errorThrown){
					statusdiv.html('<p class="ajax-error" >数据不完整或表单提交太快了！</p>').show();
				},
				success: function(data, textStatus){
					if(data.errorno=="0") {
						$("#submit").prop('disabled', true);
						statusdiv.html('<p class="ajax-success" >笔记已提交审核，感谢分享笔记！</p>').show();
						alert('笔记已提交审核，感谢分享笔记！');
					}else{
						statusdiv.html('<p class="ajax-error" >'+data.msg+'</p>').show();
					}
					commentform.find('textarea[name=comment]').val('');
				}
			});
			setTimeout(function(){
		        $("#submit").prop('disabled', false);
		    }, 10*1000);
		}
		return false;

	});
	$(".comt-author").click(function() {
		href = $(this).children("a").attr("href");
		if(href.indexOf("/note/")!=-1) {
			var win = window.open(href, '_blank');
  			win.focus();
		}
	});
	$(".comt-meta span").hover(function(){
		$(this).children(".tooltip").css({ "opacity": 1, "pointer-events": "auto"});
	},function(){
		$(this).children(".tooltip").removeAttr("style");
	});
	/*
	$(".wrapper i").hover(function(){
		$(this).siblings(".tooltip").css({ "opacity": 1, "pointer-events": "auto"});
	},function(){
		$(this).siblings(".tooltip").css({ "opacity": 0, "pointer-events": "auto"});
	});
	*/
	//Upvote.create('runoobvote-id', {callback: vote_callback});
	var ajaxurl = 'https://www.runoob.com/wp-admin/admin-ajax.php';
	var callback = function(data) {
		//console.log($('#runoobvote-id').upvote('upvoted'));
		//console.log($('#runoobvote-id').upvote('downvoted'));
		//console.log(data);
		_vote_action = data.action;
		id_arr = data.id.split('-');
		um_id= id_arr[2];
		//console.log(um_id);
		
		var re = /^[1-9]+/;
		if (re.test(um_id)) { 
			var ajax_data = {
				_vote_action: _vote_action,
				action: "pinglun_zan",
				um_id: um_id,
				um_action: "ding"
			};
			//console.log(ajax_data);
			$.post(ajaxurl,ajax_data,function(status){
				//if(status.vote_num>999) {
				//	_voteHtml = '<span style="display: block; text-align: center;font-size: 20px; color: #6a737c; margin: 8px 0;">'+kFormatter(status.vote_num) +'</span>';
				//	$("#runoobvote-id-" + um_id + " .count").hide().after(_voteHtml);
				//}
				
			});
		}
	};
	if($('#comments').length && $('.upvotejs').length){
		$('.upvotejs').upvote({id: 7658, callback: callback});
	
		$.post(ajaxurl,{"action":"pinglun_zan","postid":7658},function(data){  
			$(data).each(function(key,value) {
				$("#runoobvote-id-" + value.commid + " .upvote").addClass(value.upvotejs_class);
				$("#runoobvote-id-" + value.commid + " .downvote").addClass(value.downvote_class);
				$("#runoobvote-id-" + value.commid + " .count").text(value.upvote_count);
			})
		},'json');
		
	}
	
	
});
function isBlank(str) {
    return (!str || /^\s*$/.test(str));
}
function kFormatter(num) {
	// return num;
    return Math.abs(num) > 999 ? Math.sign(num)*((Math.abs(num)/1000).toFixed(1)) + 'k' : Math.sign(num)*Math.abs(num)
}

</script>

<link rel="stylesheet" href="../0/qa.css?1.44">
<link rel="stylesheet" type="text/css" href="../0/simditor.min.css" />
<script type="text/javascript" src=""></script>
<script type="text/javascript" src=""></script>
<script type="text/javascript" src=""></script>
<script type="text/javascript" src=""></script>
<script type="text/javascript" src=""></script>
		<div class="sidebar-box ">
				

<style>	
.responsive_ad1 { display:none; }
@media(min-width: 800px) { .responsive_ad1 {  display:block;margin:0 auto;} }
</style>
<div id="ad-336280" >

<script async src=""
     crossorigin="anonymous"></script>
<!-- 移动版 自动调整 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-5751451760833794"
     data-ad-slot="1691338467"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>
		</div>
				</div>
		
	</div>
</div>
	

<!-- 右边栏 -->
<div class="fivecol last right-column">

<style>
.sidebar-tree .double-li {
    width:300px;
}
.sidebar-tree .double-li li {
    width: 44%;
    line-height: 1.5em;
    border-bottom: 1px solid #ccc;
    float: left;
    display: inline;
}
</style>

    
        <div class="sidebar-box re-box re-box-large">
        <div class="sidebar-box recommend-here" style="margin: 0 auto;">
            <a href="javascript:void(0);" style="font-size: 16px; color:#64854c;font-weight:bold;"> <i class="fa fa-list" aria-hidden="true"></i> 分类导航</a>
        </div>
    <div class="sidebar-box sidebar-cate">
        
        <div class="sidebar-tree" >
            <ul><li style="margin: 0;"><a href="javascript:void(0);" class="tit"> HTML / CSS</a><ul class="double-li"><li><a title="HTML 教程" href="../html/html-tutorial.html">HTML 教程</a></li><li><a title="HTML5 教程" href="../html/html5-intro.html">HTML5 教程</a></li><li><a title="CSS 教程" href="../css/css-tutorial.html">CSS 教程</a></li><li><a title="CSS3 教程" href="../css3/css3-tutorial.html">CSS3 教程</a></li><li><a title="Bootstrap3 教程" href="../bootstrap/bootstrap-tutorial.html">Bootstrap3 教程</a></li><li><a title="Bootstrap4 教程" href="../bootstrap4/bootstrap4-tutorial.html">Bootstrap4 教程</a></li><li><a title="Bootstrap5 教程" href="../bootstrap5/bootstrap5-tutorial.html">Bootstrap5 教程</a></li><li><a title="Font Awesome 教程" href="../font-awesome/fontawesome-tutorial.html">Font Awesome 教程</a></li><li><a title="Foundation 教程" href="../foundation/foundation-tutorial.html">Foundation 教程</a></li></ul></li><li style="margin: 0;"><a href="javascript:void(0);" class="tit"> JavaScript</a><ul class="double-li"><li><a title="JavaScript 教程" href="../js/js-tutorial.html">JavaScript 教程</a></li><li><a title="HTML DOM 教程" href="../htmldom/htmldom-tutorial.html">HTML DOM 教程</a></li><li><a title="jQuery 教程" href="../jquery/jquery-tutorial.html">jQuery 教程</a></li><li><a title="AngularJS 教程" href="../angularjs/angularjs-tutorial.html">AngularJS 教程</a></li><li><a title="AngularJS2 教程" href="../angularjs2/angularjs2-tutorial.html">AngularJS2 教程</a></li><li><a title="Vue.js 教程" href="../vue2/vue-tutorial.html">Vue.js 教程</a></li><li><a title="Vue3 教程" href="../vue3/vue3-tutorial.html">Vue3 教程</a></li><li><a title="React 教程" href="../react/react-tutorial.html">React 教程</a></li><li><a title="TypeScript 教程" href="../typescript/ts-tutorial.html">TypeScript 教程</a></li><li><a title="jQuery UI 教程" href="../jqueryui/jqueryui-tutorial.html">jQuery UI 教程</a></li><li><a title="jQuery EasyUI 教程" href="../jeasyui/jqueryeasyui-tutorial.html">jQuery EasyUI 教程</a></li><li><a title="Node.js 教程" href="../nodejs/nodejs-tutorial.html">Node.js 教程</a></li><li><a title="AJAX 教程" href="../ajax/ajax-tutorial.html">AJAX 教程</a></li><li><a title="JSON 教程" href="../json/json-tutorial.html">JSON 教程</a></li><li><a title="Echarts 教程" href="../echarts/echarts-tutorial.html">Echarts 教程</a></li><li><a title="Chart.js 教程" href="../chartjs/chartjs-tutorial.html">Chart.js 教程</a></li><li><a title="Highcharts 教程" href="../highcharts/highcharts-tutorial.html">Highcharts 教程</a></li><li><a title="Google 地图 教程" href="../googleapi/google-maps-basic.html">Google 地图 教程</a></li></ul></li><li style="margin: 0;"><a href="javascript:void(0);" class="tit"> 服务端</a><ul class="double-li"><li><a title="Python 教程" href="../python3/python3-tutorial.html">Python 教程</a></li><li><a title="Python2.x 教程" href="../python/python-tutorial.html">Python2.x 教程</a></li><li><a title="Linux 教程" href="../linux/linux-tutorial.html">Linux 教程</a></li><li><a title="Docker 教程" href="../docker/docker-tutorial.html">Docker 教程</a></li><li><a title="Ruby 教程" href="../ruby/ruby-tutorial.html">Ruby 教程</a></li><li><a title="Java 教程" href="../java/java-tutorial.html">Java 教程</a></li><li><a title="C 教程" href="../c/c-tutorial.html">C 教程</a></li><li><a title="C++ 教程" href="../cplusplus/cpp-tutorial.html">C++ 教程</a></li><li><a title="Perl 教程" href="../perl/perl-tutorial.html">Perl 教程</a></li><li><a title="Servlet 教程" href="../servlet/servlet-tutorial.html">Servlet 教程</a></li><li><a title="JSP 教程" href="../jsp/jsp-tutorial.html">JSP 教程</a></li><li><a title="Lua 教程" href="../lua/lua-tutorial.html">Lua 教程</a></li><li><a title="Rust 教程" href="../rust/rust-tutorial.html">Rust 教程</a></li><li><a title="Scala 教程" href="../scala/scala-tutorial.html">Scala 教程</a></li><li><a title="Go 教程" href="../go/go-tutorial.html">Go 教程</a></li><li><a title="PHP 教程" href="../php/php-tutorial.html">PHP 教程</a></li><li><a title="数据结构与算法" href="../data-structures/data-structures-tutorial.html">数据结构与算法</a></li><li><a title="Django 教程" href="../django/django-tutorial.html">Django 教程</a></li><li><a title="Zookeeper 教程" href="../w3cnote/zookeeper-tutorial.html">Zookeeper 教程</a></li><li><a title="设计模式" href="../design-pattern/design-pattern-tutorial.html">设计模式</a></li><li><a title="正则表达式" href="../regexp/regexp-tutorial.html">正则表达式</a></li><li><a title="Maven 教程" href="../maven/maven-tutorial.html">Maven 教程</a></li><li><a title="Verilog 教程" href="../w3cnote/verilog-tutorial.html">Verilog 教程</a></li><li><a title="ASP 教程" href="../asp/asp-tutorial.html">ASP 教程</a></li><li><a title="AppML 教程" href="../appml/appml-tutorial.html">AppML 教程</a></li><li><a title="VBScript 教程" href="../vbscript/vbscript-tutorial.html">VBScript 教程</a></li></ul></li><li style="margin: 0;"><a href="javascript:void(0);" class="tit"> 数据库</a><ul class="double-li"><li><a title="SQL 教程" href="../sql/sql-tutorial.html">SQL 教程</a></li><li><a title="MySQL 教程" href="../mysql/mysql-tutorial.html">MySQL 教程</a></li><li><a title="PostgreSQL 教程" href="../postgresql/postgresql-tutorial.html">PostgreSQL 教程</a></li><li><a title="SQLite 教程" href="../sqlite/sqlite-tutorial.html">SQLite 教程</a></li><li><a title="MongoDB 教程" href="../mongodb/mongodb-tutorial.html">MongoDB 教程</a></li><li><a title="Redis 教程" href="../redis/redis-tutorial.html">Redis 教程</a></li><li><a title="Memcached 教程" href="../Memcached/Memcached-tutorial.html">Memcached 教程</a></li></ul></li><li style="margin: 0;"><a href="javascript:void(0);" class="tit"> 数据分析</a><ul class="double-li"><li><a title="Python 教程" href="../python3/python3-tutorial.html">Python 教程</a></li><li><a title="NumPy 教程" href="../numpy/numpy-tutorial.html">NumPy 教程</a></li><li><a title="Pandas 教程" href="../pandas/pandas-tutorial.html">Pandas 教程</a></li><li><a title="Matplotlib 教程" href="../matplotlib/matplotlib-tutorial.html">Matplotlib 教程</a></li><li><a title="Scipy 教程" href="../scipy/scipy-tutorial.html">Scipy 教程</a></li><li><a title="R 教程" href="../r/r-tutorial.html">R 教程</a></li><li><a title="Julia 教程" href="../julia/julia-tutorial.html">Julia 教程</a></li></ul></li><li style="margin: 0;"><a href="javascript:void(0);" class="tit"> 移动端</a><ul class="double-li"><li><a title="Android 教程" href="../w3cnote/android-tutorial-intro.html">Android 教程</a></li><li><a title="Swift 教程" href="../swift/swift-tutorial.html">Swift 教程</a></li><li><a title="jQuery Mobile 教程" href="../jquerymobile/jquerymobile-tutorial.html">jQuery Mobile 教程</a></li><li><a title="ionic 教程" href="../ionic/ionic-tutorial.html">ionic 教程</a></li><li><a title="Kotlin 教程" href="../kotlin/kotlin-tutorial.html">Kotlin 教程</a></li></ul></li><li style="margin: 0;"><a href="javascript:void(0);" class="tit"> XML 教程</a><ul class="double-li"><li><a title="XML 教程" href="../xml/xml-tutorial.html">XML 教程</a></li><li><a title="DTD 教程" href="../dtd/dtd-tutorial.html">DTD 教程</a></li><li><a title="XML DOM 教程" href="../dom/dom-tutorial.html">XML DOM 教程</a></li><li><a title="XSLT 教程" href="../xsl/xsl-tutorial.html">XSLT 教程</a></li><li><a title="XPath 教程" href="../xpath/xpath-tutorial.html">XPath 教程</a></li><li><a title="XQuery 教程" href="../xquery/xquery-tutorial.html">XQuery 教程</a></li><li><a title="XLink 教程" href="../xlink/xlink-tutorial.html">XLink 教程</a></li><li><a title="XPointer 教程" href="../xlink/xlink-tutorial.html">XPointer 教程</a></li><li><a title="XML Schema 教程" href="../schema/schema-tutorial.html">XML Schema 教程</a></li><li><a title="XSL-FO 教程" href="../xslfo/xslfo-tutorial.html">XSL-FO 教程</a></li><li><a title="SVG 教程" href="../svg/svg-tutorial.html">SVG 教程</a></li></ul></li><li style="margin: 0;"><a href="javascript:void(0);" class="tit"> ASP.NET</a><ul class="double-li"><li><a title="ASP.NET 教程" href="../aspnet/aspnet-tutorial.html">ASP.NET 教程</a></li><li><a title="C# 教程" href="../csharp/csharp-tutorial.html">C# 教程</a></li><li><a title="Web Pages 教程" href="../aspnet/webpages-intro.html">Web Pages 教程</a></li><li><a title="Razor 教程" href="../aspnet/razor-intro.html">Razor 教程</a></li><li><a title="MVC 教程" href="../aspnet/mvc-intro.html">MVC 教程</a></li><li><a title="Web Forms 教程" href="../aspnet/aspnet-intro.html">Web Forms 教程</a></li></ul></li><li style="margin: 0;"><a href="javascript:void(0);" class="tit"> Web Service</a><ul class="double-li"><li><a title="Web Service 教程" href="../webservices/webservices-tutorial.html">Web Service 教程</a></li><li><a title="WSDL 教程" href="../wsdl/wsdl-tutorial.html">WSDL 教程</a></li><li><a title="SOAP 教程" href="../soap/soap-tutorial.html">SOAP 教程</a></li><li><a title="RSS 教程" href="../rss/rss-tutorial.html">RSS 教程</a></li><li><a title="RDF 教程" href="../rdf/rdf-tutorial.html">RDF 教程</a></li></ul></li><li style="margin: 0;"><a href="javascript:void(0);" class="tit"> 开发工具</a><ul class="double-li"><li><a title="Eclipse 教程" href="../eclipse/eclipse-tutorial.html">Eclipse 教程</a></li><li><a title="Git 教程" href="../git/git-tutorial.html">Git 教程</a></li><li><a title="Svn 教程" href="../svn/svn-tutorial.html">Svn 教程</a></li><li><a title="Markdown 教程" href="../markdown/md-tutorial.html">Markdown 教程</a></li></ul></li><li style="margin: 0;"><a href="javascript:void(0);" class="tit"> 网站建设</a><ul class="double-li"><li><a title="HTTP 教程" href="../http/http-tutorial.html">HTTP 教程</a></li><li><a title="网站建设指南" href="../web/web-buildingprimer.html">网站建设指南</a></li><li><a title="浏览器信息" href="../browsers/browser-information.html">浏览器信息</a></li><li><a title="网站主机教程" href="../hosting/hosting-tutorial.html">网站主机教程</a></li><li><a title="TCP/IP 教程" href="../tcpip/tcpip-tutorial.html">TCP/IP 教程</a></li><li><a title="W3C 教程" href="../w3c/w3c-tutorial.html">W3C 教程</a></li><li><a title="网站品质" href="../quality/quality-tutorial.html">网站品质</a></li></ul></li></ul>            </div>
    
    </div>
    </div>
    <br>
    
    <div class="sidebar-box re-box re-box-large">
        <div class="sidebar-box recommend-here">
            <a href="javascript:void(0);">Advertisement</a>
        </div>
        <div class="re-600160" id="sidebar-right-re">
                <script async src=""></script>
        <!-- 侧栏1 -->
        <ins class="adsbygoogle"
             style="display:inline-block;width:160px;height:600px"
             data-ad-client="ca-pub-5751451760833794"
             data-ad-slot="4106274865"></ins>
        <script>
        (adsbygoogle = window.adsbygoogle || []).push({});
        </script>
                </div>
    </div>
</div></div>

</div>

<script>
var aid = 7658;
function coll() {
	$.post( '/wp-content/themes/runoob/option/user/userinfo.php', {aid:aid, action:"collarticle", opt:'add'},function( data ) {
		if(data.error==0) {
			$("#content").find("h1:first").find("a").attr("href","javascript:void(0);");
			$("#content").find("h1:first").find("img").attr("src","http://www.runoob.com/wp-content/themes/runoob/assets/img/coll2.png").css({width:32+"px",height:32+"px"});
		}
		alert(data.msg);
	},'json');
}
</script>


<!-- 反馈对话框开始 -->
<script src=""></script>
<link rel="stylesheet" href="../0/feedback.css?1.0" />
<script type="text/javascript">
$.feedback({
    ajaxURL: '/feedback/runoob_feedback.php',
	html2canvasURL: '/wp-content/themes/runoob/assets/feedback/stable/2.0/html2canvas.js',
	onClose: function () {
         window.location.reload();
    }
});
</script>
<!-- 反馈对话框结束 -->
<button class="feedback-btn feedback-btn-gray">反馈/建议</button>
<!-- 底部 -->
<div id="footer" class="mar-t50">
   <div class="runoob-block">
    <div class="runoob cf">
     <dl>
      <dt>
       在线实例
      </dt>
      <dd>
       &middot;<a target="_blank" href="../html/html-examples.html">HTML 实例</a>
      </dd>
      <dd>
       &middot;<a target="_blank" href="../css/css-examples.html">CSS 实例</a>
      </dd>
      <dd>
       &middot;<a target="_blank" href="../js/js-examples.html">JavaScript 实例</a>
      </dd>
      <dd>
       &middot;<a target="_blank" href="../ajx/ajax-examples.html">Ajax 实例</a>
      </dd>
       <dd>
       &middot;<a target="_blank" href="../jquery/jquery-examples.html">jQuery 实例</a>
      </dd>
      <dd>
       &middot;<a target="_blank" href="../xml/xml-examples.html">XML 实例</a>
      </dd>
      <dd>
       &middot;<a target="_blank" href="../java/java-examples.html">Java 实例</a>
      </dd>
     
     </dl>
     <dl>
      <dt>
      字符集&工具
      </dt>
      <dd>
       &middot; <a target="_blank" href="../charsets/html-charsets.html">HTML 字符集设置</a>
      </dd>
      <dd>
       &middot; <a target="_blank" href="../tags/html-ascii.html">HTML ASCII 字符集</a>
      </dd>
     <dd>
       &middot; <a target="_blank" href="https://c.runoob.com/front-end/6939/">JS 混淆/加密</a>
      </dd> 
      <dd>
       &middot; <a target="_blank" href="https://c.runoob.com/front-end/6232/">PNG/JPEG 图片压缩</a>
      </dd>
      <dd>
       &middot; <a target="_blank" href="../tags/html-colorpicker.html">HTML 拾色器</a>
      </dd>
      <dd>
       &middot; <a target="_blank" href="..//c.runoob.com/front-end/53">JSON 格式化工具</a>
      </dd>
      <dd>
       &middot; <a target="_blank" href="..//c.runoob.com/front-end/6680/">随机数生成器</a>
      </dd>
     </dl>
     <dl>
      <dt>
       最新更新
      </dt>
                   <dd>
       &middot;
      <a href="../matplotlib/matplotlib-imread.html" title="Matplotlib imread() 方法">Matplotlib imre...</a>
      </dd>
              <dd>
       &middot;
      <a href="../matplotlib/matplotlib-imsave.html" title="Matplotlib imsave() 方法">Matplotlib imsa...</a>
      </dd>
              <dd>
       &middot;
      <a href="../matplotlib/matplotlib-imshow.html" title="Matplotlib imshow() 方法">Matplotlib imsh...</a>
      </dd>
              <dd>
       &middot;
      <a href="../matplotlib/matplotlib-hist.html" title="Matplotlib 直方图">Matplotlib 直方图</a>
      </dd>
              <dd>
       &middot;
      <a href="../python3/python-func-object.html" title="Python object() 函数">Python object()...</a>
      </dd>
              <dd>
       &middot;
      <a href="../python3/python-ai-draw.html" title="Python AI 绘画">Python AI 绘画</a>
      </dd>
              <dd>
       &middot;
      <a href="../w3cnote/cursor-editor.html" title="神辅助 Cursor 编辑器，加入 GPT-4 让编码更轻松！">神辅助 Cursor ...</a>
      </dd>
             </dl>
     <dl>
      <dt>
       站点信息
      </dt>
      <dd>
       &middot;
       <a target="_blank" href="mailto:admin@runoob.com" rel="external nofollow">意见反馈</a>
       </dd>
      <dd>
       &middot;
      <a target="_blank" href="../disclaimer">免责声明</a>
       </dd>
      <dd>
       &middot;
       <a target="_blank" href="../aboutus">关于我们</a>
       </dd>
      <dd>
       &middot;
      <a target="_blank" href="../archives">文章归档</a>
      </dd>
    
     </dl>
    
     <div class="search-share">
      <div class="app-download">
        <div>
         <strong>关注微信</strong>
        </div>
      </div>
      <div class="share">
      <img width="128" height="128" src="/wp-content/themes/runoob/assets/images/qrcode.png" />
       </div>
     </div>
     
    </div>
   </div>
   <div class="w-1000 copyright">
     Copyright &copy; 2013-2023    <strong><a href="../" target="_blank">菜鸟教程</a></strong>&nbsp;
    <strong><a href="../" target="_blank">runoob.com</a></strong> All Rights Reserved. 备案号：<a target="_blank" rel="nofollow" href="https://beian.miit.gov.cn/">闽ICP备15012807号-1</a>
   </div>
  </div>
  <div class="fixed-btn">
    <a class="go-top" href="javascript:void(0)" title="返回顶部"> <i class="fa fa-angle-up"></i></a>
    <a class="qrcode"  href="javascript:void(0)" title="关注我们"><i class="fa fa-qrcode"></i></a>
    <a class="writer" style="display:none" href="javascript:void(0)"   title="标记/收藏"><i class="fa fa-star" aria-hidden="true"></i></a>
    <!-- qrcode modal -->
    <div id="bottom-qrcode" class="modal panel-modal hide fade in">
      <h4>微信关注</h4>
      <div class="panel-body"><img alt="微信关注" width="128" height="128" src="/wp-content/themes/runoob/assets/images/qrcode.png"></div> 
    </div>
  </div>

 <div style="display:none;">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-84264393-2"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-84264393-2');
</script>
<script>
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?3eec0b7da6548cf07db3bc477ea905ee";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();
</script>

</div>
<script>
window.jsui={
    www: 'https://www.runoob.com',
    uri: 'https://www.runoob.com/wp-content/themes/runoob'
};
</script>

<script src=""></script>
<script src=""></script>

</body>
</html>